﻿#include "CFileTask.h"
#include "ClientFileSocket.h"
#include "TransFileWgt.h"
#include "unit.h"
#include "CIULog.h"

#include <QMutexLocker>
#include <QDebug>

CFileTask::CFileTask(ClientFileSocket *fSocket, QObject *parent)
    : QThread(parent),
      m_pFileSocket(fSocket),
      m_pCurrentSendTask(nullptr),
      m_bStop(false),
      m_bBusy(false)
{
    //上传文件
    connect(this,
            &CFileTask::sigUploadFile,
            m_pFileSocket,
            &ClientFileSocket::SltUploadFile,
            Qt::QueuedConnection);

    //下载文件
    connect(this,
            &CFileTask::sigDownloadFile,
            m_pFileSocket,
            &ClientFileSocket::SltDownloadFile,
            Qt::QueuedConnection);

    //文件传输状态返回
    connect(m_pFileSocket,
            &ClientFileSocket::sigTransFileStatus,
            this,
            &CFileTask::SltTransFileStatus,
            Qt::QueuedConnection);
}

CFileTask::~CFileTask()
{
    //不用清除任务队列，程序退出的时候只要将该线程退出即可
    //ClearAllItems();
}

//设置标志位true，唤醒线程
void CFileTask::Stop()
{
    m_bStop = true;
    m_conditon.wakeOne();
}

//添加一个文件发送任务
bool CFileTask::AddSendItem(TransFileWgt *pItem)
{
    if (nullptr == pItem)
        return false;

    QMutexLocker guard(&m_mutex);
    m_SendFileTasks.append(pItem);
    m_conditon.wakeOne();

    return true;
}

//添加一个文件接收任务
bool CFileTask::AddRecvItem(TransFileWgt *pItem)
{
    if (nullptr == pItem)
        return false;

    QMutexLocker guard(&m_mutex);
    m_RecvFileTasks.append(pItem);
    m_conditon.wakeOne();

    return true;
}

//移除一个文件发送任务
void CFileTask::RemoveSendItem(TransFileWgt *pItem)
{
    if (nullptr == pItem)
        return;

    //正在下载或上传的项使用信号让其停止
    if(m_pCurrentSendTask == pItem)
    {
        //取消信号槽
        disconnect(m_pFileSocket,
                   &ClientFileSocket::sigUpdateTransFileProgress,
                   m_pCurrentSendTask,
                   &TransFileWgt::SltUpdateProgressValue);
        //socket停止发送
        m_pFileSocket->StopSend();
        m_pCurrentSendTask = nullptr;

        //唤醒任务线程，看是否还有文件需要发送
        QMutexLocker guard(&m_mutex);
        m_bBusy = false;
        //修改文件传输标志
        m_conditon.wakeOne();
    }else
    {
        QMutexLocker guard(&m_mutex);
        //未开始下载或上传的项直接移除
        QList<TransFileWgt*>::iterator iter = m_SendFileTasks.begin();
        for(; iter!=m_SendFileTasks.end(); ++iter)
        {
            if(pItem ==*iter)
            {
                m_SendFileTasks.erase(iter);
                break;
            }
        }
    }
}

//移除一个文件接收任务
void CFileTask::RemoveRecvItem(TransFileWgt *pItem)
{
    if (nullptr == pItem)
        return;

    //正在下载或上传的项使用信号让其停止
    if(m_pCurrentSendTask == pItem)
    {
        //取消信号槽
        disconnect(m_pFileSocket,
                   &ClientFileSocket::sigUpdateTransFileProgress,
                   m_pCurrentSendTask,
                   &TransFileWgt::SltUpdateProgressValue);
        //socket停止发送
        m_pFileSocket->StopRecv();

        //唤醒任务线程，看是否还有文件需要发送
        QMutexLocker guard(&m_mutex);
        m_pCurrentSendTask = nullptr;
        m_bBusy = false;
        //修改文件传输标志
        m_conditon.wakeOne();

    }else
    {
        QMutexLocker guard(&m_mutex);
        //未开始下载或上传的项直接移除
        QList<TransFileWgt*>::iterator iter = m_RecvFileTasks.begin();
        for(; iter!=m_RecvFileTasks.end(); ++iter)
        {
            if(pItem ==*iter)
            {
                m_RecvFileTasks.erase(iter);
                break;
            }
        }
    }
}

//清空所有待发送文件
void CFileTask::ClearAllItems()
{
    //如果还有文件在发送
    if(m_pCurrentSendTask != nullptr)
    {
        m_pFileSocket->StopSend();
        disconnect(m_pFileSocket,
                   &ClientFileSocket::sigUpdateTransFileProgress,
                   m_pCurrentSendTask,
                   &TransFileWgt::SltUpdateProgressValue);
    }

    QMutexLocker guard(&m_mutex);

    m_SendFileTasks.clear();
}

//进行文件传输，交给socket处理
void CFileTask::HandleItem(TransFileWgt *pFileItem)
{
    if(nullptr == pFileItem)
        return;

    //开始进行处理
    pFileItem->m_isPending = false;
    m_pCurrentSendTask = pFileItem;
    connect(m_pFileSocket,
            &ClientFileSocket::sigUpdateTransFileProgress,
            m_pCurrentSendTask,
            &TransFileWgt::SltUpdateProgressValue,
            Qt::QueuedConnection);

    if(FILE_ITEM_UPLOAD_CHAT_OFFLINE_FILE == pFileItem->m_nFileType)
    {
        Q_EMIT sigUploadFile(pFileItem->m_filePath,pFileItem->m_fileMd5);
    }else if(FILE_ITEM_DOWNLOAD_CHAT_OFFLINE_FILE == pFileItem->m_nFileType)
    {
        Q_EMIT sigDownloadFile(pFileItem->m_filePath,pFileItem->m_fileMd5);
    }
}

void CFileTask::run()
{
    LOG_INFO("Start a new thread.");
    while (!m_bStop)
    {
        TransFileWgt* pFileItem;
        {
            QMutexLocker guard(&m_mutex);
            //发送接受列表都为空，或者当前发送接受都处于忙的状态需要等待
            while ( (m_SendFileTasks.isEmpty() && m_RecvFileTasks.isEmpty())
                   || (m_bBusy) )
            {
                if (m_bStop)
                    return;
                m_conditon.wait(&m_mutex);
            }
            //如果发送任务空闲且有发送队列有任务待发送
            if( m_SendFileTasks.size() > 0)
            {
                pFileItem = m_SendFileTasks.takeFirst();
                m_bBusy = true;
            }
            //如果接受任务空闲且接受队列有任务待发送
            if(m_RecvFileTasks.size() > 0)
            {
                pFileItem = m_RecvFileTasks.takeFirst();
                m_bBusy = true;
            }
        }
        //修改文件传输标志
        HandleItem(pFileItem);
    }
}

//发件发送状态返回,这里返回的是socket传输文件的状态，不包括用户取消导致的发送失败
void CFileTask::SltTransFileStatus(qint8 status)
{
    LOG_INFO("Transfile status: %d.",status);
    if(status == FILE_UPLOAD_FAILED)
    {
        m_pCurrentSendTask->TransFileStatus(FILE_UPLOAD_FAILED,tr("File Send Failed!"));
    }else if(status == FILE_UPLOAD_SUCCESS)
    {
        m_pCurrentSendTask->TransFileStatus(FILE_UPLOAD_SUCCESS,tr("File Send Successed!"));
    }else if(status == FILE_DOWNLOAD_FAILED)
    {
        m_pCurrentSendTask->TransFileStatus(FILE_DOWNLOAD_FAILED,tr("File Recv Failed!"));
    }else if(status == FILE_DOWNLOAD_SUCCESS)
    {
        m_pCurrentSendTask->TransFileStatus(FILE_DOWNLOAD_SUCCESS,tr("File Recv Successed!"));
    }

    disconnect(m_pFileSocket,
               &ClientFileSocket::sigUpdateTransFileProgress,
               m_pCurrentSendTask,
               &TransFileWgt::SltUpdateProgressValue);

    //唤醒任务线程，看是否还有文件需要发送
    QMutexLocker guard(&m_mutex);
    m_pCurrentSendTask = nullptr;
    m_bBusy = false;
    //修改文件传输标志
    m_conditon.wakeOne();
}
